package com.cb.web.wasf;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.jsp.PageContext;

/**
 * @author CBO
 */
public abstract class State implements Serializable {

    private boolean refreshedAfterDesynchronization;// TODO : Certainement à remonter dans la session...
    private List<Message> messages;

    public static State getCurrentSessionState(PageContext context) {
        DefaultSession defaultSession = DefaultSession.getFromPageContext(context);
        return defaultSession != null ? defaultSession.getCurrentState() : null;
    }

    public State() {
        this.refreshedAfterDesynchronization = false;
        this.messages = new ArrayList<Message>();
    }

    protected StateOrView handleRequest(Request request) throws ServletException {
        Method method;
        try {
            method = this.getClass().getMethod(request.getEvent(), new Class[]{Request.class});
            try {
                if (State.class.isAssignableFrom(method.getReturnType())) {
                    return new StateOrView((State) method.invoke(this, request));
                } else if (View.class.isAssignableFrom(method.getReturnType())) {
                    return new StateOrView((View) method.invoke(this, request));
                } else {
                    throw new UnExpectedEventException(request.getEvent());
                }
            } catch (IllegalAccessException iae) {
                throw new UnExpectedEventException(request.getEvent());
            } catch (InvocationTargetException ite) {
                throw new ServletException(ite);
            }
        } catch (NoSuchMethodException nsme) {
            throw new UnExpectedEventException(request.getEvent());
        }
    }

    public abstract View getView();

    public boolean isRefreshedAfterDesynchronization() {
        return refreshedAfterDesynchronization;
    }

    public void setRefreshedAfterDesynchronization(boolean refreshedAfterDesynchronization) {
        this.refreshedAfterDesynchronization = refreshedAfterDesynchronization;
    }

    public List<Message> getMessages() {
        return Collections.unmodifiableList(messages);
    }

    public void clearMessages() {
        this.messages.clear();
    }

    public void addMessage(Message message) {
        this.messages.add(message);
    }

    public boolean hasMessage() {
        return !this.messages.isEmpty();
    }

    public static class StateOrView {

        private State state;
        private View view;

        public StateOrView(State state) {
            this.state = state;
        }

        public StateOrView(View view) {
            this.view = view;
        }

        public State getState() {
            return state;
        }

        public View getView() {
            return view;
        }
    }
}
